///////////////////////////////////////////////////////////
///////////////// Have an itch? Scratch it! ///////////////
///////////////////////// SCRATCH /////////////////////////
/////////////////////  A MUD  Server   ////////////////////
///////////////////// By: Jared Devall ////////////////////
/////////////////////      Thanks:     ////////////////////
/////////////////////  DIKU/Merc/ROM   ////////////////////
///////////////////// Aetas/Deus Gang  ////////////////////
/////////////////////       Beej       ////////////////////
///////////////////////////////////////////////////////////

#include <list>
#include "definitions.h"
#include "commands.h"
#include "commandTable.h"
#include "character.h"
#include "world.h"
#include "stringutil.h"
#include "split.h"
#include "timestamp.h"
#include "vEditHandler.h"

using namespace std;

// aCommand definitions
// (Keep in alphabetical order... it's MUCH easier)
nCmdBody::nCmdBody() {
	SetName( "body" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdBody::Execute( Character* c, const string& args ) {

	if ( c->getNote() != NULL ) {
		c->setVEdit( true );
		vEditList::Instance().act( c, args );
	}

	c->Send( "No note selected.\n\r" );

	return true;
}

nCmdCommands::nCmdCommands( ) {
	SetName( "commands" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdCommands::Execute( Character* c, const string &args ) {
	std::string buf;
	std::string temp;
	list< Command* >::iterator it;
	int f = 0;

	if ( c->getLevel() >= HEAD ) {
		buf << "\n\r\t{chead (level " << HEAD << ") commands:{x\n\r";
		for ( it = nCommandTable::Instance()._commands.begin(); it != nCommandTable::Instance()._commands.end(); ++it ) {
			if ( (*it)->_level == HEAD ) {
				if ( !(*it)->_enabled )
					buf << "{w";
				if ( f == 0 ) {
					buf << "  " << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				} else {
					buf << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				}
				if ( !(*it)->_enabled )
					buf << "{x";
			    f++;
			    if ( f == 5 ) {
					buf << "\n\r";
					f = 0;
				}
			}
		}
	}
	f = 0;
	if ( c->getLevel() >= GOD ) {
		buf << "\n\r\t{cgod (level " << GOD << ") commands:{x\n\r";
		for ( it = nCommandTable::Instance()._commands.begin(); it != nCommandTable::Instance()._commands.end(); ++it ) {
			if ( (*it)->_level == GOD ) {
				if ( !(*it)->_enabled )
					buf << "{w";
				if ( f == 0 ) {
					buf << "  " << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				} else {
					buf << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				}
				if ( !(*it)->_enabled )
					buf << "{x";
			    f++;
			    if ( f == 5 ) {
					buf << "\n\r";
					f = 0;
				}
			}
		}
	}
	f = 0;
	if ( c->getLevel() >= BUILDER ) {
		buf << "\n\r\t{cbuilder (level " << BUILDER << ") commands:{x\n\r";
		for ( it = nCommandTable::Instance()._commands.begin(); it != nCommandTable::Instance()._commands.end(); ++it ) {
			if ( (*it)->_level == BUILDER ) {
				if ( !(*it)->_enabled )
					buf << "{w";
				if ( f == 0 ) {
					buf << "  " << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				} else {
					buf << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				}
				if ( !(*it)->_enabled )
					buf << "{x";
			    f++;
			    if ( f == 5 ) {
					buf << "\n\r";
					f = 0;
				}
			}
		}
	}
	f = 0;
	buf << "\n\r\t{c-- Commands --{x \n\r";
	for ( it = nCommandTable::Instance()._commands.begin(); it != nCommandTable::Instance()._commands.end(); ++it ) {
		if ( (*it)->_level == 1 ) {
				if ( !(*it)->_enabled )
					buf << "{w";
				if ( f == 0 ) {
					buf << "  " << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				} else {
					buf << (*it)->_name.c_str() << spaces( 12, (*it)->_name.c_str(), temp );
				}
				if ( !(*it)->_enabled )
					buf << "{x";
		    f++;
		    if ( f == 5 ) {
				buf << "\n\r";
				f = 0;
			}
		}
	}


	c->Send( buf );

	return true;
}

nCmdDelete::nCmdDelete() {
	SetName( "delete" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdDelete::Execute( Character* c, const string& args ) {
	std::string buf;

	if ( c->getNote() != NULL ) {
		c->dropNote( c->getNote() );
		c->setNote( 0 );
		nCmdList cmdList;
		cmdList.Execute( c, "" );
		return true;
	}

	c->Send( "You must select a note before you may delete it.\n\r" );
	return false;
}

nCmdExit::nCmdExit() {
	SetName( "exit" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdExit::Execute( Character* c, const string& args ) {

	c->SetStatus( CONNECTED );
	c->setNote( NULL );
	c->Send( "You have left the post office.\n\r" );

	return true;
}

nCmdList::nCmdList() {
	SetName( "list" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdList::Execute( Character* c, const string& args ) {
	std::string buf;

	if ( c->getNotes().empty() ) {
		c->Send( "You don't have any unsent notes.\n\r" );
		return true;
	}

	buf << "\t\t{!WUnsent Notes{x:\n\r";

	for ( std::list< Note* >::iterator it = c->getNotes().begin(); it != c->getNotes().end(); it++ )
		buf << "number: " << (*it)->getId() << " to: " << (*it)->getRecipient() << "\n\r\tsubject: " << (*it)->getSubject() << "\n\r";

	c->Send( buf );

	return true;
}

nCmdNew::nCmdNew() {
	SetName( "new" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdNew::Execute( Character* c, const string& args ) {
	bool found = false;
	std::list< Board* >::iterator it;

	if ( args.empty() ) {
		c->Send( "sytanx: new <board>    creates a new note to be posted to the given board\n\r" );
		return false;
	}

	for ( it = World::Instance().getBoards().begin(); it != World::Instance().getBoards().end(); it++ )
		if ( (*it)->getNumber() == atoi( args.c_str() ) ) {
			found = true;
			c->setNote( c->addNote() );
			c->getNote()->setBoard( (*it)->getName() );
			if ( c->getNote()->getBoard() != "Personal" )
				c->getNote()->setRecipient( "all" );
			c->getNote()->setAuthor( c->getName() );
		}

	if ( !found ) {
		c->setNote( 0 );
		c->Send( "Invalid board number.\n\r" );
		return false;
	}

	nCmdList cmdList;
	cmdList.Execute( c, "" );

	return true;
}

nCmdRecipient::nCmdRecipient() {
	SetName( "recipient" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdRecipient::Execute( Character* c, const string& args ) {
	std::string buf;

	if ( c->getNote() != NULL ) {
		if ( c->getNote()->getBoard() != "Personal" ) {
			c->Send( "You can't change the recipient on a public board.\n\r" );
			return false;
		}
		c->getNote()->setRecipient( args );
		nCmdView cmdView;
		cmdView.Execute( c, "" );
		return true;
	}

	c->Send( "No note selected.\n\r" );

	return false;
}

nCmdSelect::nCmdSelect() {
	SetName( "select" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdSelect::Execute( Character* c, const string& args ) {
	std::string buf;
	int note = atoi( args.c_str() );

	for ( std::list< Note* >::iterator n_it = c->getNotes().begin(); n_it != c->getNotes().end(); n_it++ )
		if ( (*n_it)->getId() == note ) {
			c->setNote( *n_it );
			buf << "You've selected note " << c->getNote()->getId() << "\n\r";
			c->Send( buf );
			return true;
		}

	c->Send( "That note doesn't exist.\n\r" );
	return false;
}

nCmdSend::nCmdSend() {
	SetName( "send" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdSend::Execute( Character* c, const string& args ) {
	std::string buf;
	bool sendable = true;
	Note* note = 0;
	std::list< Board* >::iterator it;

	if ( c->getNote() != NULL ) {
		note = c->getNote();
		if ( note->getRecipient().empty() ) {
			sendable = false;
			buf << "You must specify a recipient.\n\r";
		}
		if ( note->getSubject().empty() ) {
			sendable = false;
			buf << "You must specify a subject.\n\r";
		}
		if ( !sendable ) {
			c->Send( buf );
			return false;
		} else {
			for ( it = World::Instance().getBoards().begin(); it != World::Instance().getBoards().end(); it++ )
				if ( (*it)->getName() == note->getBoard() ) {
					note->setSent( Timestamp::Instance().GetDateTime() );
					*((*it)->addNote()) = (*note);
					c->dropNote( note );
					note = 0;
					c->setNote( 0 );
					c->Send( "Note sent!\n\r" );
					return true;
				}
		}
		
	}

	c->Send( "You must select a note before you may send it.\n\r" );
	return false;
}

nCmdSubject::nCmdSubject() {
	SetName( "subject" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdSubject::Execute( Character* c, const string& args ) {
	std::string buf;

	if ( c->getNote() != NULL ) {
		c->getNote()->setSubject( args );
		nCmdView cmdView;
		cmdView.Execute( c, "" );
		return true;
	}

	c->Send( "No note selected.\n\r" );

	return false;
}

nCmdView::nCmdView() {
	SetName( "view" );
	SetLevel( 1 );
	SetEnabled( true );
	SetOmniset( false );
}

bool nCmdView::Execute( Character* c, const string& args ) {
	std::string buf;
	int note = 0;
	std::list< Board* >::iterator it;

	if ( args.empty() ) {
		if ( c->getNote() != NULL ) {
			buf << "Board:     " << c->getNote()->getBoard();
			buf << "\nRecipient: " << c->getNote()->getRecipient() << "\n\r";
			buf << "Subject:   " << c->getNote()->getSubject() << "\n\r\n\r";
			buf << c->getNote()->getBody() << "\n\r";
			c->Send( buf );
			return true;
		}
	} else {
		note = atoi( args.c_str() );
		for ( std::list< Note* >::iterator n_it = c->getNotes().begin(); n_it != c->getNotes().end(); n_it++ )
			if ( (*n_it)->getId() == note ) {
				buf << "Recipient: " << (*n_it)->getRecipient() << "\n\r";
				buf << "Subject:   " << (*n_it)->getSubject() << "\n\r\n\r";
				buf << (*n_it)->getBody() << "\n\r";
				c->Send( buf );
				return true;
			}
		c->Send( "That note wasn't found.\n\r" );
		return false;
	}

	c->Send( "syntax: view <number>      displays note <number>\n\r        view               displays currently selected note\n\r" );
	return false;
}
